﻿using Domain.Config;
using Domain.Event;
using Domain.IRepositorys;
using Domain.Model;
using Domain.Types;
using Infrastructure.Error;
using Infrastructure.UniOfWorkBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Domain.Services
{
    public class WalletService
    {
        public IWalletRepository walletRepository { get; set; }
        public IInComeWalletLogRepository inComeWalletLogRepository { get; set; }
        public IChargeWalletLogRepository chargeWalletLogRepository { get; set; }
        public IWithDrawRepository withDrawRepository { get; set; }
        public IUserRepository userRepository { get; set; }
        public IEFUnitOfWork efUnitOfWork { get; set; }

        private bool CheckWithDrawRule(UserInfoAggregate u, WalletAggregate wallet, PayChannelEnum payChannel, int money)
        {
            var txMinMoney = u.GetTraderLevelConfig<int>("提现配置.最低提现金额");
            var txMaxMoney = u.GetTraderLevelConfig<int>("提现配置.每笔最大金额");

            var txNum = u.GetTraderLevelConfig<int>("提现配置.每天提现次数");


            if (money < txMinMoney) throw new BizException("申请提现失败，小于最低提现金额");
            if (money > txMaxMoney) throw new BizException("申请提现失败，大于单笔最大提现金额");
            var dayWithDrawNum = withDrawRepository.Entities.Where(i => i.UserID == u.ID && i.CT >= DateTime.Today).Count();
            if (dayWithDrawNum >= txNum) throw new BizException($"申请提现失败，超过每天提现{txNum}次");

            switch (payChannel)
            {
                default:
                case PayChannelEnum.支付宝:
                    if (string.IsNullOrWhiteSpace(wallet.AliPayAccount)) throw new BizException("提现支付宝账号设置为空，请先设置支付宝账号");
                    if (string.IsNullOrWhiteSpace(wallet.AliPayAccountName)) throw new BizException("提现支付宝账号真实姓名设置为空，请先设置支付宝账号真实姓名");
                    break;
                case PayChannelEnum.微信App:
                    if (string.IsNullOrWhiteSpace(wallet.WxPayAccount)) throw new BizException("提现微信账号设置为空，请先设置微信账号");
                    if (string.IsNullOrWhiteSpace(wallet.WxPayAccountName)) throw new BizException("提现微信账号真实姓名设置为空，请先设置微信账号真实姓名");
                    break;
            }

            return true;
        }
        public WithDrawAggregate WithDrawMoneyByCharge(int uid, PayChannelEnum payChannel, int money)
        {
            var u = userRepository.GetByKey(uid);
            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);

            CheckWithDrawRule(u, wallet, payChannel, money);


            var chazhi = money - wallet.ChargeBlance;
            if (chazhi > 0) throw new BizException("提现失败,您当前输入的提现的金额大于发布余额!");

            var txMoneyNeedAudit = u.GetTraderLevelConfig<int>("提现配置.大于多少金额需要审核");

            var taxPer = u.GetTraderLevelConfig<int>("提现配置.提现手续费");
            var status = (money >= txMoneyNeedAudit) ? WithDrawStatus.待审核 : WithDrawStatus.待打款;

            //生成提现审核记录
            WithDrawAggregate withDrawAggregate = new WithDrawAggregate();
            withDrawAggregate.AccountType = payChannel;
            withDrawAggregate.CT = withDrawAggregate.UT = DateTime.Now;
            withDrawAggregate.Money = money;
            withDrawAggregate.Status = status;
            withDrawAggregate.TaxFee = money * taxPer / 100;
            withDrawAggregate.UserID = uid;
            withDrawAggregate.ReceiveMoney = withDrawAggregate.Money - withDrawAggregate.TaxFee;
            withDrawAggregate.WalletType = WalletType.充值钱包;
            withDrawAggregate.AuditStatus = WithDrawAuditStatus.待人工审核;
            if (status == WithDrawStatus.待打款)
            {
                withDrawAggregate.AuditStatus = WithDrawAuditStatus.机审通过;
                withDrawAggregate.AuditOperator = "M";
                //操作打款
                wallet.AddDomainEvent(new WithDrawEvent()
                {
                    WithDrawIdentity = withDrawAggregate.Identity,
                    UserID = uid
                });
            }

            withDrawRepository.Insert(withDrawAggregate);
            ChangeChargeWallet(uid, -money, withDrawAggregate.TaxFee, withDrawAggregate.Identity.ToString("N"), FinancialBizType.用户提现, "用户提现", "用户提现-提现审核ID");

            if (efUnitOfWork.Commit() > 0) return withDrawAggregate;

            return null;
        }

        public WithDrawAggregate WithDrawMoneyByInCome(int uid, PayChannelEnum payChannel, int money)
        {
            var u = userRepository.GetByKey(uid);
            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);

            CheckWithDrawRule(u, wallet, payChannel, money);


            var chazhi = money - wallet.InComeBlance;
            if (chazhi > 0) throw new BizException("提现失败,您当前输入的提现的金额大于用户余额!");

            var txMoneyNeedAudit = u.GetTraderLevelConfig<int>("提现配置.大于多少金额需要审核");

            var taxPer = u.GetTraderLevelConfig<int>("提现配置.提现手续费");
            var status = (money >= txMoneyNeedAudit) ? WithDrawStatus.待审核 : WithDrawStatus.待打款;

            //生成提现审核记录
            WithDrawAggregate withDrawAggregate = new WithDrawAggregate();
            withDrawAggregate.AccountType = payChannel;
            withDrawAggregate.CT = withDrawAggregate.UT = DateTime.Now;
            withDrawAggregate.Money = money;
            withDrawAggregate.Status = status;
            withDrawAggregate.TaxFee = money * taxPer / 100;
            withDrawAggregate.UserID = uid;
            withDrawAggregate.ReceiveMoney = withDrawAggregate.Money - withDrawAggregate.TaxFee;
            withDrawAggregate.WalletType = WalletType.佣金钱包;
            withDrawRepository.Insert(withDrawAggregate);
            withDrawAggregate.AuditStatus = WithDrawAuditStatus.待人工审核;
            if (status == WithDrawStatus.待打款)
            {
                withDrawAggregate.AuditStatus = WithDrawAuditStatus.机审通过;
                withDrawAggregate.AuditOperator = "M";
                //操作打款
                wallet.AddDomainEvent(new WithDrawEvent()
                {
                    WithDrawIdentity = withDrawAggregate.Identity,
                    UserID = uid
                });
            }

            withDrawRepository.Insert(withDrawAggregate);
            ChangeInComeWallet(uid, -money, withDrawAggregate.TaxFee, withDrawAggregate.TaxFee, null,0, FinancialBizType.用户提现, "用户提现", "用户提现-提现审核ID");

            if (efUnitOfWork.Commit() > 0) return withDrawAggregate;

            return null;
        }


        public ChargeWalletLogAggregate ChangeChargeWallet(int uid, int changeMoney, int systemInComeMoney, string bizNO, FinancialBizType financialBizType, string bizDesc, string remark, string Data = null, string InstitutionNO=default, bool InstitutionTradeSuccess=false,string Message=default)
        {
            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);
            if (wallet == null) throw new BizException($"未找到用户钱包！");

            if (wallet.ChargeBlance + changeMoney < 0) throw new BizException($"用户余额不足！");

            //记录
            ChargeWalletLogAggregate chargeWalletLogAggregate = new ChargeWalletLogAggregate();

            chargeWalletLogAggregate.UserID = uid;
            chargeWalletLogAggregate.WalletID = wallet.ID;
            chargeWalletLogAggregate.BizNO = bizNO;
            chargeWalletLogAggregate.BizType = financialBizType.ToString();
            chargeWalletLogAggregate.BizDesc = bizDesc;
            chargeWalletLogAggregate.ChangeMoney = changeMoney;
            chargeWalletLogAggregate.HistoryBlance = wallet.ChargeBlance;
            chargeWalletLogAggregate.Remark = remark;

            chargeWalletLogRepository.Insert(chargeWalletLogAggregate);

            wallet.AddDomainEvent(new FinancialEvent()
            {
                BizNO = bizNO,
                CT = DateTime.Now,
                Data = Data,
                FinancialWalletType = WalletType.充值钱包,
                FinancialBizType = financialBizType,
                HistoryWalletBlance = wallet.ChargeBlance,
                UserInComeMoney = changeMoney,
                SystemInComeMoney = systemInComeMoney,
                Remark = remark,
                UserID = uid,
                AliPayID= InstitutionNO,
                IsSuccess= InstitutionTradeSuccess,
                Message=Message
            });

            wallet.ChargeBlance += changeMoney;

            return chargeWalletLogAggregate;
        }

        public InComeWalletLogAggregate ChangeInComeWallet(int uid, int inComeMoney,int tax, int systemInComeMoney, string bizNO,int fromUid, FinancialBizType financialBizType, string bizDesc, string remark, string Data = null)
        {
            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);
            if (wallet == null) throw new BizException($"未找到用户钱包！");

            if (wallet.InComeBlance < inComeMoney) throw new BizException($"用户余额不足！");

            //记录
            InComeWalletLogAggregate incomeWalletLogAggregate = new InComeWalletLogAggregate();

            incomeWalletLogAggregate.UserID = uid;
            incomeWalletLogAggregate.WalletID = wallet.ID;
            incomeWalletLogAggregate.BizNO = bizNO;
            incomeWalletLogAggregate.BizType = financialBizType.ToString();
            incomeWalletLogAggregate.BizDesc = bizDesc;
            incomeWalletLogAggregate.ChangeMoney = inComeMoney;
            incomeWalletLogAggregate.HistoryBlance = wallet.ChargeBlance;
            incomeWalletLogAggregate.Remark = remark;
            incomeWalletLogAggregate.Data = Data;
            incomeWalletLogAggregate.Tax = tax;
            incomeWalletLogAggregate.FromUid = fromUid;

            inComeWalletLogRepository.Insert(incomeWalletLogAggregate);

            wallet.AddDomainEvent(new FinancialEvent()
            {
                BizNO = bizNO,
                CT = DateTime.Now,
                Data = Data,
                FinancialWalletType = WalletType.佣金钱包,
                FinancialBizType = financialBizType,
                HistoryWalletBlance = wallet.ChargeBlance,
                UserInComeMoney = inComeMoney,
                SystemInComeMoney = systemInComeMoney,
                Remark = remark,
                UserID = uid

            });

            wallet.InComeBlance += inComeMoney;

            return incomeWalletLogAggregate;
        }
    }
}
